﻿using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace PickGold.Generic
{
	/// <summary>
	/// 定义类型为比较两个对象而实现的方法。
	/// </summary>
	/// <typeparam name="T">要比较的对象的类型。</typeparam>
	public class CComparer<T> : Comparer<T>
	{
		private object _Tag;
		private CompareHandler _Handler;

		/// <summary>
		/// 构造一个比较两个对象而实现的方法的对象
		/// </summary>
		/// <param name="handler">比较两个对象委托</param>
		public CComparer(CompareHandler handler)
		{
			this._Handler = handler;
		}

		/// <summary>
		/// 构造一个比较两个对象而实现的方法的对象
		/// </summary>
		/// <param name="comparer">比较两个对象的方法的对象</param>
		public CComparer(CComparer<T> comparer)
		{
			this._Handler = comparer._Handler;
		}

		/// <summary>
		/// 构造一个比较两个对象而实现的方法的对象
		/// </summary>
		/// <param name="comparer">比较两个对象的方法的对象</param>
		public CComparer(IComparer<T> comparer)
		{
			this._Handler = new CComparer<T>.CompareHandler(comparer.Compare);
		}

		/// <summary>
		/// 构造一个比较两个对象而实现的方法的对象
		/// </summary>
		/// <param name="comparer">比较两个对象的方法的对象</param>
		public CComparer(object comparer)
		{
			var handler = comparer as Delegate;
			if (handler != null)
			{
				handler = Delegate.CreateDelegate(typeof(CompareHandler), handler.Target, handler.Method, false);
				this._Handler = handler as CompareHandler;
				return;
			}

			var method = typeof(IComparer).GetMethods()[0].Name;
			handler = Delegate.CreateDelegate(typeof(CompareHandler), comparer, method, true, false);
			if (handler == null)
				handler = Delegate.CreateDelegate(typeof(CompareHandler), comparer.GetType(), method, true, false);
			this._Handler = handler as CompareHandler;
		}

		/// <summary>
		/// 比较两个对象并返回一个值，指示一个对象是小于、等于还是大于另一个对象。
		/// </summary>
		/// <param name="x">要比较的第一个对象。</param>
		/// <param name="y">要比较的第二个对象。</param>
		/// <returns>值 条件 小于零x 小于 y。零x 等于 y。大于零x 大于 y。</returns>
		public override int Compare(T x, T y)
		{
			if (this._Handler == null)
			{
				if (x != null)
				{
					var x0 = x as IComparable<T>;
					if (x0 != null)
						return x0.CompareTo(y);

					var x1 = x as IComparable;
					if (x1 != null)
						return x1.CompareTo(y);
				}

				if (y != null)
				{
					var y0 = y as IComparable<T>;
					if (y0 != null)
						return y0.CompareTo(x);

					var y1 = y as IComparable;
					if (y1 != null)
						return y1.CompareTo(x);
				}

				//var method = typeof(T).GetMethod(MethodBase.GetCurrentMethod().Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
				var handler = Delegate.CreateDelegate(typeof(CompareHandler), typeof(T), MethodBase.GetCurrentMethod().Name, true, false);
				if (handler != null)
					return (int)handler.Method.Invoke(null, new object[] { x, y });
			}

			return this._Handler(x, y);
			//throw new NotImplementedException();
		}

		/// <summary>
		/// 附加数据
		/// </summary>
		public object Tag
		{
			set
			{
				this._Tag = value;
			}
			get
			{
				return this._Tag;
			}
		}

		/// <summary>
		/// 比较两个对象并返回一个值，指示一个对象是小于、等于还是大于另一个对象。
		/// </summary>
		/// <param name="x">要比较的第一个对象。</param>
		/// <param name="y">要比较的第二个对象。</param>
		/// <returns>值 条件 小于零x 小于 y。零x 等于 y。大于零x 大于 y。</returns>
		public delegate int CompareHandler(T x, T y);
	}
}
